home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-12-08 | 19.6 KB | 748 lines | [TEXT/MPS ] |
- /*
- File: Selection.pp
-
- Contains: Selection class implementation
-
- Written by: Steve Smith
-
- Copyright: © 1995 by Apple Computer, Inc., all rights reserved.
- */
-
- // -- Compiler/Preprocessor Switches --
-
- #ifndef _COMPILERDEFS_
- #include "CompDefs.h"
- #endif
-
- // -- OpenDoc Utilities --
-
- #ifndef _EXCEPT_
- // Exceptions define several important macros (ie. CHECKENV)
- // which are used in the SOM method dispatch glue. If Except.h
- // is not included early enough, exceptions may not be thrown
- // correctly when returning from a SOM method with the "ev" parameter set.
- #include <Except.h>
- #endif
-
- // -- PanelEditor Includes --
-
- #ifndef _SELECTION_
- #include "Selection.h"
- #endif
-
- #ifndef _PANELEDITOR_
- #include "PanelEditor.h"
- #endif
-
- #ifndef _PANELEDITORDEF_
- #include "PanelEditorDef.h"
- #endif
-
- #ifndef _PANELEDITORGLOBALS_
- #include "PanelEditorGlobals.h"
- #endif
-
- #ifndef _LISTITEM_
- #include "ListItem.h"
- #endif
-
- #ifndef _UNDOPE_
- #include "UndoPE.h"
- #endif
-
- #ifndef _SAMPLECOLLECTIONS_
- #include "SampleCollections.h"
- #endif
-
- // -- OpenDoc Includes --
-
- #ifndef _ODTYPES_
- #include <ODTypes.h>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StdDefs_defined
- #include <StdDefs.xh>
- #endif
-
- #ifndef SOM_ODArbitrator_xh
- #include <Arbitrat.xh>
- #endif
-
- #ifndef SOM_ODClipboard_xh
- #include <Clipbd.xh>
- #endif
-
- #ifndef SOM_ODUndo_xh
- #include <Undo.xh>
- #endif
-
- #ifndef SOM_ODStorageUnit_xh
- #include <StorageU.xh>
- #endif
-
- #ifndef SOM_ODDragAndDrop_xh
- #include <DragDrp.xh>
- #endif
-
- #ifndef SOM_ODShape_xh
- #include <Shape.xh>
- #endif
-
- // -- OpenDoc Utilities --
-
- #ifndef _BARRAY_
- #include <BArray.h>
- #endif
-
- #ifndef _ODUTILS_
- #include <ODUtils.h>
- #endif
-
- #ifndef _STORUTIL_
- #include <StorUtil.h>
- #endif
-
- #ifndef _USERSRCM_
- #include <UseRsrcM.h>
- #endif
-
- #ifndef _ODDEBUG_
- #include <ODDebug.h>
- #endif
-
- #ifndef _ODNEW_
- #include <ODNew.h>
- #endif
-
- #ifndef _FOCUSLIB_
- #include <FocusLib.h>
- #endif
-
- #ifndef _TEMPOBJ_
- #include <TempObj.h>
- #endif
-
- // -- Macintosh Includes --
-
- #ifndef __DRAG__
- #include <Drag.h>
- #endif
-
-
- #pragma segment PanelEditorSelection
-
- //------------------------------------------------------------------------------
- // Method: Constructor
- //------------------------------------------------------------------------------
-
- CSelection::CSelection(PanelEditor* owner, ODSession* session)
- {
- fItems = kODNULL;
- fOwner = owner;
- fSession = session;
- fInited = kODFalse;
- }
-
- //------------------------------------------------------------------------------
- // Method: Destructor
- //------------------------------------------------------------------------------
-
- CSelection::~CSelection()
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
-
- Environment* ev = somGetGlobalEnvironment();
-
- // Remove any remaining items from the selection list.
- this->Empty(ev);
- }
-
- //------------------------------------------------------------------------------
- // Method: InitSelection
- //------------------------------------------------------------------------------
-
- void CSelection::InitSelection()
- {
- fItems = new CList;
- fInited = kODTrue;
- }
-
- //------------------------------------------------------------------------------
- // Method: Add
- // Description: Add an item to the selection and set its selected state.
- //------------------------------------------------------------------------------
-
- void CSelection::Add(Environment* ev, CListItem* item)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fItems != kODNULL, kAssertionFailed);
-
- // Select the item.
- item->SetSelected(ev, kODTrue);
- // Add the item from the selection list.
- fItems->Add((ODPtr)item);
- // Release the selection's reference to the item.
- item->Acquire();
- }
-
- //------------------------------------------------------------------------------
- // Method: Remove
- // Description: This method is called during
- //------------------------------------------------------------------------------
-
- void CSelection::Remove(Environment* ev, CListItem* item)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fItems != kODNULL, kAssertionFailed);
-
- // Unselect the item.
- item->SetSelected(ev, kODFalse);
- // Remove the item from the selection list.
- fItems->Remove((ODPtr)item);
- // Release the selection's reference to the item.
- item->Release(ev);
- }
-
- //------------------------------------------------------------------------------
- // Method: Empty
- //
- // Description: This method is called to empty the current selection. The update
- // parameter specifies whether the facet's of the items should have
- // their selected states udpated. There's no need to do this if the
- // item is going away.
- //------------------------------------------------------------------------------
-
- void CSelection::Empty(Environment* ev, ODBoolean update)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fItems != kODNULL, kAssertionFailed);
-
- // Iterate over the list of items in the selection
- // and remove them.
- CListIterator fiter(fItems);
- for ( CListItem* item = (CListItem*)fiter.First();
- fiter.IsNotComplete();
- item = (CListItem*)fiter.Next() )
- {
- fiter.RemoveCurrent();
- if ( update )
- item->SetSelected(ev, kODFalse);
- item->Release(ev);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: IsEmpty
- //
- // Description: This method is called during
- //------------------------------------------------------------------------------
-
- ODBoolean CSelection::IsEmpty()
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fItems != kODNULL, kAssertionFailed);
-
- return ( fItems->Count() == 0 );
- }
-
- //------------------------------------------------------------------------------
- // Method: ClearItems
- //
- // Description: Remove the items in the selection from the part's list by
- // iterating over the selection and asking the part to remove the
- // items one-at-a-time.
- //------------------------------------------------------------------------------
-
- void CSelection::ClearItems(Environment* ev)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fItems != kODNULL, kAssertionFailed);
- ASSERT(fOwner != kODNULL, kAssertionFailed);
-
- // We can't remove the items from the list we are iterating over. So we have
- // to make a copy of the current list and iterate over that.
-
- // Copy the list.
- CList* list = new CList;
- CListIterator fiter(fItems);
- for ( CListItem* item = (CListItem*)fiter.First();
- fiter.IsNotComplete();
- item = (CListItem*)fiter.Next() )
- {
- list->Add((ODPtr)item);
- }
-
- // Iterate over the copy, removing each item.
- CListIterator liter(list);
- for ( CListItem* anitem = (CListItem*)liter.First();
- liter.IsNotComplete();
- anitem = (CListItem*)liter.Next() )
- {
- // Ask the owner to remove the item from internal collections.
- fOwner->RemoveListItem(ev, anitem);
- // Detach the item from the document frame hierarchy.
- anitem->Detach(ev);
- // Remove the item from the selection.
- this->Remove(ev, anitem);
- }
- delete list;
- }
-
- //------------------------------------------------------------------------------
- // Method: CaptureItems
- //
- // Description: Duplicate the current selection for Undo.
- //------------------------------------------------------------------------------
-
- CList* CSelection::CaptureItems()
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fItems != kODNULL, kAssertionFailed);
-
- // Clone the selection list to be used for Undo/Redo.
-
- CList* list = new CList;
-
- CListIterator fiter(fItems);
- for ( CListItem* item = (CListItem*)fiter.First();
- fiter.IsNotComplete();
- item = (CListItem*)fiter.Next() )
- {
- list->Add((ODPtr)item);
- item->Acquire();
- }
-
- return list;
- }
-
- //------------------------------------------------------------------------------
- // Method: Activate
- //
- // Description: Notify the items in the selection that an activate/deactivate or
- // suspend/resume event is being processed. This is necessary to
- // ensure the items are displayed correctly.
- //------------------------------------------------------------------------------
-
- void CSelection::Activate(Environment* ev, ODFrame* frame, ODBoolean activate)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
-
- TempODWindow window = frame->AcquireWindow(ev);
- if ( window )
- {
- ODID windowID = window->GetID(ev);
-
- CListIterator fiter(fItems);
- for ( CListItem* item = (CListItem*)fiter.First();
- fiter.IsNotComplete();
- item = (CListItem*)fiter.Next() )
- {
- // The items only care about "suspend" events.
- item->ActivationChanged(ev, windowID, activate);
- }
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: Write
- //
- // Description: Write the items in the selection to the storageUnit passed in.
- //------------------------------------------------------------------------------
-
- void CSelection::Write(Environment* ev, ODStorageUnit* storageUnit)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fItems != kODNULL, kAssertionFailed);
-
- ODDraft* fromDraft = ODGetDraft(ev, fOwner->GetSelf());
- ODDraft* toDraft = ODGetDraft(ev, storageUnit);
- ODDraftKey draftKey;
-
- ODVolatile(fromDraft);
- ODVolatile(draftKey);
-
- draftKey = fromDraft->BeginClone(ev, toDraft, kODNULLID, kODCloneCopy);
-
- TRY
- // Clone the part in the selection to the storageUnit.
- CListIterator fiter(fItems);
- CListItem* item = (CListItem*)fiter.First();
-
- item->ClonePart(ev, storageUnit, draftKey);
-
- fromDraft->EndClone(ev, draftKey);
- CATCH_ALL
- fromDraft->AbortClone(ev, draftKey);
- // consume exceptions.
- ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // Method: Cut
- //
- // Description: Handle the Edit menu command to cut the selected items.
- //------------------------------------------------------------------------------
-
- void CSelection::Cut(Environment* ev, ODFrame* frame)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fOwner != kODNULL, kAssertionFailed);
-
- // Call the "copy" method to do the work.
- this->Copy(ev, frame);
-
- // Allow the user to undo/redo the clipboard operation.
- this->PushUndoState(ev, kUndoCut, kODSingleAction);
-
- // Clear the items in the selection.
- this->ClearItems(ev);
- }
-
- //------------------------------------------------------------------------------
- // Method: Copy
- //
- // Description: Handle the Edit menu command to copy the selected items.
- //------------------------------------------------------------------------------
-
- void CSelection::Copy(Environment* ev, ODFrame* frame)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fOwner != kODNULL, kAssertionFailed);
-
- ODArbitrator* arbitrator = fSession->GetArbitrator(ev);
- ODClipboard* clipboard = fSession->GetClipboard(ev);
-
- // Acquire the clipboard focus.
- if ( arbitrator->RequestFocus(ev, gGlobals->fClipboardFocus, frame) )
- {
- // Clear out the old junk.
- clipboard->Clear(ev);
- ODStorageUnit* su = clipboard->GetContentStorageUnit(ev);
-
- // Write out the current selection.
- this->Write(ev, su);
-
- // Relinquish the clipboard focus.
- arbitrator->RelinquishFocus(ev, gGlobals->fClipboardFocus, frame);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: Clear
- //
- // Description: Handle the Edit menu command to clear the selected items.
- //------------------------------------------------------------------------------
-
- void CSelection::Clear(Environment* ev, ODFrame* frame)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fOwner != kODNULL, kAssertionFailed);
-
- // Allow the user to undo/redo the clipboard operation.
- this->PushUndoState(ev, kUndoClear, kODSingleAction);
-
- // Clear the items in the selection.
- this->ClearItems(ev);
- }
-
- //------------------------------------------------------------------------------
- // Method: ShowPartInfo
- //
- // Description: This method is called to display the Part Info dialog for each
- // item in the selection.
- //------------------------------------------------------------------------------
-
- void CSelection::ShowPartInfo(Environment* ev, ODFrame* frame)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fOwner != kODNULL, kAssertionFailed);
-
- // Iterate over the selection.
- CListIterator fiter(fItems);
- for ( CListItem* item = (CListItem*)fiter.First();
- fiter.IsNotComplete();
- item = (CListItem*)fiter.Next() )
- {
- // Ask each item to display part info for itself.
- item->DoPartInfo(ev, frame);
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: Undo
- //
- // Description: This method is called to undo a previous action.
- //------------------------------------------------------------------------------
-
- void CSelection::Undo(Environment* ev, CUndo* action)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
-
- switch ( action->GetType() ) {
- case kUndoCut:
- case kUndoPaste:
- case kUndoClear:
- case kUndoDrop:
-
- default:;
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: Redo
- //
- // Description: This method is called to redo a previously undone action.
- //------------------------------------------------------------------------------
-
- void CSelection::Redo(Environment* ev, CUndo* action)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
-
- switch ( action->GetType() ) {
- case kUndoCut:
- case kUndoPaste:
- case kUndoClear:
- case kUndoDrop:
-
- default:;
- }
- }
-
- //------------------------------------------------------------------------------
- // Method: PushUndoState
- //
- // Description: This method is called to capture and push the current state of
- // of the selection so that it may later be un/redone.
- //------------------------------------------------------------------------------
-
- void CSelection::PushUndoState(Environment* ev, ODUShort undoType, ODActionType actionType)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
- ASSERT(fOwner != kODNULL, kAssertionFailed);
- ASSERT(fSession != kODNULL, kAssertionFailed);
-
- ODIText* undoString = kODNULL;
- ODIText* redoString = kODNULL;
-
- // Store the state to be undone/redone.
- CUndo* undoData = new CUndo;
-
- undoData->SetType(undoType);
- undoData->SetSelection(this->CaptureItems());
-
- // Create an byte array to store the undo information.
- ODActionData action;
- action._length = sizeof(CUndo*);
- action._maximum = sizeof(CUndo*);
- action._buffer = (octet*) &undoData;
-
- ODUndo* undo = fSession->GetUndo(ev);
-
- Str255 text;
- // Get the undo string
- ODGetIndString(text, kUndoStringResID, undoType);
- undoString = CreateIText(gGlobals->fEditorsScript, gGlobals->fEditorsLanguage, (StringPtr)&text);
-
- // Get the redo string
- ODGetIndString(text, kUndoStringResID, undoType+1);
- redoString = CreateIText(gGlobals->fEditorsScript, gGlobals->fEditorsLanguage, (StringPtr)&text);
-
- // Push all the information onto the OpenDoc undo stack.
- TRY
- undo->AddActionToHistory(ev, fOwner->GetSelf(), &action, actionType, undoString, redoString);
- CATCH_ALL
- DisposeIText(undoString);
- DisposeIText(redoString);
- ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // Method: CheckForDrag
- //
- // Description: This method is called to test for the user's dragging of the
- // selection.
- //------------------------------------------------------------------------------
-
- ODBoolean CSelection::CheckForDrag(Environment* ev, ODEventData* event)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
-
- ODBoolean yes = WaitMouseMoved(event->where);
- return yes;
- }
-
- //------------------------------------------------------------------------------
- // Method: Drag
- //
- // Description: This method is called to initiate a drag operation for the
- // current selection.
- //------------------------------------------------------------------------------
-
- void CSelection::Drag(Environment* ev, ODFacet* facet, ODEventData* event,
- ODEventInfo* eventInfo)
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
-
- ODDropResult result = kODDropFail;
- ODPart* part = kODNULL;
- ODFrame* frame = facet->GetFrame(ev);
- ODSLong error = noErr;
-
- ODVolatile(part);
- ODVolatile(error);
-
- ODDragAndDrop* dragdrop = fSession->GetDragAndDrop(ev);
-
- // Remove existing data from the drag container.
- dragdrop->Clear(ev);
-
- // Add our content property to the drag container.
- ODStorageUnit* dragdropSU = dragdrop->GetContentStorageUnit(ev);
- dragdropSU->AddProperty(ev, kODPropContents);
- dragdropSU->AddValue(ev, kPanelEditorKind);
-
- // Externalize the current selection.
- this->Write(ev, dragdropSU);
-
- // Calculate the drag feedback offset in global coordinates.
- Point pt = {0,0};
- {
- CFocus initiateDrawing(ev, eventInfo->embeddedFacet);
- LocalToGlobal(&pt);
- }
-
- // Get the embedded frame shape as a region for dragging feedback.
- ODFrame* embFrame = eventInfo->embeddedFacet->GetFrame(ev);
-
- RgnHandle selectionRgn = kODNULL;
- {
- CListIterator fiter(fItems);
- CListItem* item = (CListItem*)fiter.First();
- selectionRgn = item->GetSelectedRegion(ev);
- }
-
- OffsetRgn((RgnHandle)selectionRgn, pt.h, pt.v);
-
- // Let the rest of OpenDoc know we are dragging the embedded frame.
- embFrame->SetDragging(ev, kODTrue);
-
- RgnHandle dragRgn = NewRgn();
- CopyRgn((RgnHandle) selectionRgn, dragRgn);
- InsetRgn(dragRgn, -1, -1);
- DiffRgn(dragRgn, (RgnHandle) selectionRgn, dragRgn);
-
- // Start Undo recording.
- this->PushUndoState(ev, kUndoDrag, kODBeginAction);
-
- // Capture the "current" selection so we can operate on it if necessary.
- CList* currentSelection = this->CaptureItems();
-
- // Create Byte Arrays for the 2 dynamic parameters
- ODByteArray dragRgnBA = CreateByteArrayStruct(&dragRgn, sizeof(RgnHandle));
- ODByteArray eventBA = CreateByteArrayStruct(&event, sizeof(ODEventData*));
-
- ODVolatile(dragRgnBA);
- ODVolatile(eventBA);
-
- TRY
- result = dragdrop->StartDrag(ev, frame, kODDragImageRegionHandle, &dragRgnBA, &part, &eventBA);
-
- // Dispose byte arrays
- DisposeByteArrayStruct(dragRgnBA);
- DisposeByteArrayStruct(eventBA);
-
- // Handle drop result.
- if ( result == kODDropMove )
- {
- // Get a valid item to add to the selection.
- CListItem* nearItem = fOwner->GetItemNearSelection();
-
- CListIterator fiter(currentSelection);
- for ( CListItem* item = (CListItem*)fiter.First();
- fiter.IsNotComplete();
- item = (CListItem*)fiter.Next() )
- {
- // Ask the owner to remove the item from internal collections.
- fOwner->RemoveListItem(ev, item);
- // Remove the item from the selection.
- this->Remove(ev, item);
- // Detach the item from the document frame hierarchy.
- item->Detach(ev);
- // Remove and release the item.
- fiter.RemoveCurrent();
- item->Release(ev);
- }
-
- // Update the selection.
- fOwner->UpdateSelection(ev, nearItem);
- // Dirty the draft.
- fOwner->SetDirty(ev);
- }
-
- CATCH_ALL
- // Dispose byte arrays
- DisposeByteArrayStruct(dragRgnBA);
- DisposeByteArrayStruct(eventBA);
-
- // Save the error so we can return it.
- error = ErrorCode();
- ENDTRY
-
- delete currentSelection;
-
- // Start Undo recording.
- this->PushUndoState(ev, kUndoDrag, kODEndAction);
-
- // Let the rest of OpenDoc know we are dragging the embedded frame.
- embFrame->SetDragging(ev, kODFalse);
-
- // Dispose drag selection feedback region.
- DisposeRgn(dragRgn);
-
- // The destination part must be released.
- ODSafeReleaseObject(part);
-
- // If there was an error during dragging, make sure to report it.
- THROW_IF_ERROR(error);
- }
-
- //------------------------------------------------------------------------------
- // Method: GetFirstItem
- //
- // Description:
- //------------------------------------------------------------------------------
-
- CListItem* CSelection::GetFirstItem()
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
-
- CListIterator iter(fItems);
- return (CListItem*) iter.First();
- }
-
- //------------------------------------------------------------------------------
- // Method: GetLastItem
- //
- // Description:
- //------------------------------------------------------------------------------
-
- CListItem* CSelection::GetLastItem()
- {
- ASSERT(fInited != kODFalse, kAssertionFailed);
-
- CListIterator iter(fItems);
- return (CListItem*) iter.Last();
- }
-
-
-
-
-
-
-
-
-
-
-
-
-